package com.rskj.cashbook.service.iml;

import com.rskj.cashbook.dao.AutoAccountingRuleDao;
import com.rskj.cashbook.iexception.BusinessException;
import com.rskj.cashbook.service.AutoAccountingRuleService;
import com.rskj.cashbook.vo.AutoAccountingRule;
import com.rskj.cashbook.vo.AutoAccountingExecutionLog;
import com.rskj.cashbook.vo.CashBook;
import com.rskj.cashbook.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Comparator;
import java.util.stream.Collectors;
import com.rskj.cashbook.vo.AutoAccountingRuleTemplate;

/**
 * 自动记账规则服务实现类
 * @author system
 */
@Service
@Slf4j
public class AutoAccountingRuleServiceImpl implements AutoAccountingRuleService {

    @Autowired
    private AutoAccountingRuleDao autoAccountingRuleDao;
    
    @Autowired
    private CashBookService cashBookService;
    
    @Override
    @Transactional
    public AutoAccountingRule createRule(AutoAccountingRule rule) throws BusinessException {
        // 验证规则
        if (!validateRule(rule)) {
            throw new BusinessException("规则配置无效");
        }
        
        // 设置基础信息
        rule.setId(UUID.randomUUID().toString());
        rule.setIsActive(true);
        rule.setExecuteCount(0);
        
        // 设置默认值
        if (rule.getAmount() == null) {
            rule.setAmount(BigDecimal.ZERO);
        }
        if (rule.getStartDate() == null) {
            rule.setStartDate(java.time.LocalDate.now());
        }
        if (rule.getPayWay() == null || rule.getPayWay().trim().isEmpty()) {
            rule.setPayWay("OTHER");
        }
        if (rule.getPayPlat() == null || rule.getPayPlat().trim().isEmpty()) {
            rule.setPayPlat("未知平台");
        }
        if (rule.getFrequencyValue() == null) {
            rule.setFrequencyValue(1);
        }
        
        // 计算下次执行时间
        calculateNextExecuteTime(rule);
        
        // 保存规则
        autoAccountingRuleDao.insert(rule);
        
        return rule;
    }
    
    @Override
    @Transactional
    public AutoAccountingRule updateRule(AutoAccountingRule rule) {
        // 验证规则
        if (!validateRule(rule)) {
            throw new BusinessException("规则配置无效");
        }
        
        // 计算下次执行时间
        calculateNextExecuteTime(rule);
        
        // 更新规则
        autoAccountingRuleDao.update(rule);
        
        return rule;
    }
    
    @Override
    @Transactional
    public boolean deleteRule(String id) {
        return autoAccountingRuleDao.deleteById(id) > 0;
    }
    
    @Override
    public AutoAccountingRule getRuleById(String id) {
        return autoAccountingRuleDao.selectById(id);
    }
    
    @Override
    public List<AutoAccountingRule> getUserRules(String userId) {
        return autoAccountingRuleDao.selectByUserId(userId);
    }
    
    @Override
    public List<AutoAccountingRule> getActiveRules() {
        return autoAccountingRuleDao.selectActiveRules();
    }
    
    @Override
    @Transactional
    public boolean toggleRuleStatus(String id) {
        AutoAccountingRule rule = getRuleById(id);
        if (rule == null) {
            return false;
        }
        
        rule.setIsActive(!rule.getIsActive());
        if (rule.getIsActive()) {
            calculateNextExecuteTime(rule);
        }
        
        return autoAccountingRuleDao.update(rule) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutoAccountingExecutionLog executeRule(String ruleId) {
        AutoAccountingRule rule = getRuleById(ruleId);
        if (rule == null || !rule.getIsActive()) {
            return createExecutionLog(ruleId, "FAILED", "规则不存在或已禁用", null);
        }
        
        // 检查是否应该执行
        if (!shouldExecuteRule(rule)) {
            return createExecutionLog(ruleId, "SKIPPED", "规则不需要执行", null);
        }
        
        try {
            // 执行记账
            CashBook cashBook = createCashBookFromRule(rule);
            int insertResult = cashBookService.insert(cashBook);
            
            if (insertResult <= 0) {
                throw new RuntimeException("插入记账记录失败");
            }
            
            // 更新规则执行信息
            updateRuleExecutionInfo(rule);
            
            return createExecutionLog(ruleId, "SUCCESS", null, cashBook.getId());
            
        } catch (Exception e) {
            log.error("执行规则 {} 时发生错误: {}", ruleId, e.getMessage(), e);
            return createExecutionLog(ruleId, "FAILED", e.getMessage(), null);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AutoAccountingExecutionLog> executeRules(List<String> ruleIds) {
        List<AutoAccountingExecutionLog> logs = new ArrayList<>();
        for (String ruleId : ruleIds) {
            logs.add(executeRule(ruleId));
        }
        return logs;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutoAccountingExecutionLog manualExecuteRule(String ruleId) {
        AutoAccountingRule rule = getRuleById(ruleId);
        if (rule == null) {
            return createExecutionLog(ruleId, "FAILED", "规则不存在", null);
        }
        
        try {
            // 执行记账
            CashBook cashBook = createCashBookFromRule(rule);
            int insertResult = cashBookService.insert(cashBook);
            
            if (insertResult <= 0) {
                throw new RuntimeException("插入记账记录失败");
            }
            
            // 更新规则执行信息
            updateRuleExecutionInfo(rule);
            
            return createExecutionLog(ruleId, "SUCCESS", null, cashBook.getId());
            
        } catch (Exception e) {
            log.error("手动执行规则 {} 时发生错误: {}", ruleId, e.getMessage(), e);
            return createExecutionLog(ruleId, "FAILED", e.getMessage(), null);
        }
    }
    
    @Override
    public void calculateNextExecuteTime(AutoAccountingRule rule) {
        if (rule.getFrequency() == null) {
            return;
        }
        
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nextTime = null;
        
        switch (rule.getFrequency()) {
            case "DAILY":
                nextTime = calculateNextDailyTime(rule, now);
                break;
            case "WEEKLY":
                nextTime = calculateNextWeeklyTime(rule, now);
                break;
            case "MONTHLY":
                nextTime = calculateNextMonthlyTime(rule, now);
                break;
            case "YEARLY":
                nextTime = calculateNextYearlyTime(rule, now);
                break;
        }
        
        rule.setNextExecuteTime(nextTime);
    }
    
    @Override
    public boolean validateRule(AutoAccountingRule rule) {
        // 规则名称是必填的
        if (rule.getRuleName() == null || rule.getRuleName().trim().isEmpty()) {
            return false;
        }
        
        // 规则类型是必填的
        if (rule.getRuleType() == null || rule.getRuleType().trim().isEmpty()) {
            return false;
        }
        
        // 频率是必填的
        if (rule.getFrequency() == null || rule.getFrequency().trim().isEmpty()) {
            return false;
        }
        
        // 付款人和收款人是必填的
        if (rule.getPayUserName() == null || rule.getPayUserName().trim().isEmpty()) {
            return false;
        }
        if (rule.getForUserName() == null || rule.getForUserName().trim().isEmpty()) {
            return false;
        }
        
        // 备注可以为空，但如果有值不能为空字符串
        if (rule.getRemark() != null && rule.getRemark().trim().isEmpty()) {
            return false;
        }
        
        // 金额可以为0或null（表示不固定金额）
        if (rule.getAmount() != null && rule.getAmount().compareTo(BigDecimal.ZERO) < 0) {
            return false;
        }
        
        // 开始日期可以为空（表示立即生效）
        // 结束日期可以为空（表示永不过期）
        
        return true;
    }
    
    @Override
    public List<AutoAccountingRule> searchRules(String ruleName, String ruleType, Boolean isActive, String userId) {
        return autoAccountingRuleDao.selectByCondition(ruleName, ruleType, isActive, userId);
    }
    
    @Override
    public List<AutoAccountingExecutionLog> getExecutionHistory(String ruleId) {
        // TODO: 实现执行历史查询逻辑
        return new ArrayList<>();
    }
    
    @Override
    public Map<String, Object> getStats() {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            // 获取规则数量统计
            List<AutoAccountingRule> allRules = autoAccountingRuleDao.selectAllRules();
            List<AutoAccountingRule> activeRules = autoAccountingRuleDao.selectActiveRules();
            
            int totalRules = allRules.size();
            int activeRulesCount = activeRules.size();
            int inactiveRulesCount = totalRules - activeRulesCount;
            
            stats.put("totalRules", totalRules);
            stats.put("activeRules", activeRulesCount);
            stats.put("inactiveRules", inactiveRulesCount);
            
            // 获取执行统计
            List<AutoAccountingExecutionLog> allLogs = autoAccountingRuleDao.selectAllExecutionLogs();
            
            int totalExecutions = allLogs.size();
            int successExecutions = (int) allLogs.stream()
                    .filter(log -> "SUCCESS".equals(log.getExecuteResult()))
                    .count();
            int failedExecutions = totalExecutions - successExecutions;
            
            stats.put("totalExecutions", totalExecutions);
            stats.put("successExecutions", successExecutions);
            stats.put("failedExecutions", failedExecutions);
            
            // 获取最后执行时间和下次计划执行时间
            if (!allLogs.isEmpty()) {
                AutoAccountingExecutionLog lastLog = allLogs.stream()
                        .max(Comparator.comparing(AutoAccountingExecutionLog::getExecuteTime))
                        .orElse(null);
                
                if (lastLog != null) {
                    stats.put("lastExecutionTime", lastLog.getExecuteTime().toString());
                }
            }
            
            // 获取下次计划执行时间（从启用的规则中找最近的）
            if (!activeRules.isEmpty()) {
                AutoAccountingRule nextRule = activeRules.stream()
                        .filter(rule -> rule.getNextExecuteTime() != null)
                        .min(Comparator.comparing(AutoAccountingRule::getNextExecuteTime))
                        .orElse(null);
                
                if (nextRule != null) {
                    stats.put("nextScheduledTime", nextRule.getNextExecuteTime().toString());
                }
            }
            
            // 如果没有数据，设置默认值
            if (!stats.containsKey("lastExecutionTime")) {
                stats.put("lastExecutionTime", "");
            }
            if (!stats.containsKey("nextScheduledTime")) {
                stats.put("nextScheduledTime", "");
            }
            
        } catch (Exception e) {
            // 如果出现异常，设置默认值
            stats.put("totalRules", 0);
            stats.put("activeRules", 0);
            stats.put("inactiveRules", 0);
            stats.put("totalExecutions", 0);
            stats.put("successExecutions", 0);
            stats.put("failedExecutions", 0);
            stats.put("lastExecutionTime", "");
            stats.put("nextScheduledTime", "");
        }
        
        return stats;
    }
    
    @Override
    public com.github.pagehelper.PageInfo<AutoAccountingRule> getRulesWithPageHelper(int pageNumber, int pageSize, String ruleName, String ruleType, Boolean isActive) {
        // 使用PageHelper进行分页
        com.github.pagehelper.PageHelper.startPage(pageNumber, pageSize);
        
        // 获取数据
        List<AutoAccountingRule> rules = autoAccountingRuleDao.selectByCondition(ruleName, ruleType, isActive, null);
        
        // 返回PageInfo对象
        return new com.github.pagehelper.PageInfo<>(rules);
    }
    
    @Override
    public com.github.pagehelper.PageInfo<AutoAccountingRule> getRulesWithPageHelperAndSort(int pageNumber, int pageSize, String ruleName, String ruleType, Boolean isActive, String sortBy, String sortOrder) {
        // 使用PageHelper进行分页
        com.github.pagehelper.PageHelper.startPage(pageNumber, pageSize);
        
        // 设置排序
        if (sortBy != null && !sortBy.isEmpty()) {
            String orderBy = sortBy;
            if ("ASC".equalsIgnoreCase(sortOrder)) {
                orderBy += " ASC";
            } else {
                orderBy += " DESC";
            }
            com.github.pagehelper.PageHelper.orderBy(orderBy);
        }
        
        // 获取数据
        List<AutoAccountingRule> rules = autoAccountingRuleDao.selectByCondition(ruleName, ruleType, isActive, null);
        
        // 返回PageInfo对象
        return new com.github.pagehelper.PageInfo<>(rules);
    }
    
    @Override
    public com.github.pagehelper.PageInfo<AutoAccountingRule> getUserRulesWithPageHelper(String userId, int pageNumber, int pageSize, String ruleName, String ruleType, Boolean isActive) {
        // 使用PageHelper进行分页
        com.github.pagehelper.PageHelper.startPage(pageNumber, pageSize);
        
        // 获取用户规则
        List<AutoAccountingRule> userRules = autoAccountingRuleDao.selectByUserId(userId);
        
        // 应用过滤条件
        List<AutoAccountingRule> filteredRules = userRules.stream()
                .filter(rule -> {
                    boolean matchesName = ruleName == null || ruleName.isEmpty() || 
                            rule.getRuleName().toLowerCase().contains(ruleName.toLowerCase());
                    boolean matchesType = ruleType == null || ruleType.isEmpty() || 
                            ruleType.equals(rule.getRuleType());
                    boolean matchesActive = isActive == null || isActive.equals(rule.getIsActive());
                    
                    return matchesName && matchesType && matchesActive;
                })
                .collect(Collectors.toList());
        
        // 返回PageInfo对象
        return new com.github.pagehelper.PageInfo<>(filteredRules);
    }
    
    @Override
    public com.github.pagehelper.PageInfo<AutoAccountingExecutionLog> getExecutionLogsWithPageHelper(int pageNumber, int pageSize, String ruleId, String executeResult, String startDate, String endDate) {
        // 使用PageHelper进行分页
        com.github.pagehelper.PageHelper.startPage(pageNumber, pageSize);
        
        // 设置排序（按执行时间倒序）
        com.github.pagehelper.PageHelper.orderBy("execute_time DESC");
        
        // 获取所有执行日志
        List<AutoAccountingExecutionLog> allLogs = autoAccountingRuleDao.selectAllExecutionLogs();
        
        // 应用过滤条件
        List<AutoAccountingExecutionLog> filteredLogs = allLogs.stream()
                .filter(log -> {
                    boolean matchesRuleId = ruleId == null || ruleId.isEmpty() || 
                            ruleId.equals(log.getRuleId());
                    boolean matchesResult = executeResult == null || executeResult.isEmpty() || 
                            executeResult.equals(log.getExecuteResult());
                    
                    return matchesRuleId && matchesResult;
                })
                .collect(Collectors.toList());
        
        // 返回PageInfo对象
        return new com.github.pagehelper.PageInfo<>(filteredLogs);
    }
    
    @Override
    public com.github.pagehelper.PageInfo<AutoAccountingRuleTemplate> getTemplatesWithPageHelper(int pageNumber, int pageSize, String category, String keyword) {
        // 使用PageHelper进行分页
        com.github.pagehelper.PageHelper.startPage(pageNumber, pageSize);
        
        // 设置排序（按使用次数倒序）
        com.github.pagehelper.PageHelper.orderBy("usage_count DESC");
        
        // 获取所有模板
        List<AutoAccountingRuleTemplate> allTemplates = getRuleTemplates();
        
        // 应用过滤条件
        List<AutoAccountingRuleTemplate> filteredTemplates = allTemplates.stream()
                .filter(template -> {
                    boolean matchesCategory = category == null || category.isEmpty() || 
                            category.equals(template.getCategory());
                    boolean matchesKeyword = keyword == null || keyword.isEmpty() || 
                            template.getTemplateName().toLowerCase().contains(keyword.toLowerCase()) ||
                            template.getDescription().toLowerCase().contains(keyword.toLowerCase());
                    
                    return matchesCategory && matchesKeyword;
                })
                .collect(Collectors.toList());
        
        // 返回PageInfo对象
        return new com.github.pagehelper.PageInfo<>(filteredTemplates);
    }
    
    @Override
    public List<AutoAccountingRuleTemplate> getRuleTemplates() {
        // TODO: 实现从数据库获取模板列表
        List<AutoAccountingRuleTemplate> templates = new ArrayList<>();
        
        // 添加一些默认模板
        templates.add(createDefaultTemplate("日常餐饮", "EXPENSE", "每天自动记录餐饮支出"));
        templates.add(createDefaultTemplate("交通出行", "EXPENSE", "工作日自动记录交通费用"));
        templates.add(createDefaultTemplate("工资收入", "INCOME", "每月自动记录工资收入"));
        templates.add(createDefaultTemplate("房租支出", "EXPENSE", "每月自动记录房租支出"));
        
        return templates;
    }
    
    @Override
    public AutoAccountingRule createRuleFromTemplate(String templateId, Map<String, Object> customizations) {
        // TODO: 实现从模板创建规则的逻辑
        AutoAccountingRule rule = new AutoAccountingRule();
        
        // 设置基础信息
        rule.setId(UUID.randomUUID().toString());
        rule.setIsActive(true);
        rule.setExecuteCount(0);
        
        // 应用自定义配置
        if (customizations != null) {
            if (customizations.containsKey("amount")) {
                rule.setAmount(new BigDecimal(customizations.get("amount").toString()));
            }
            if (customizations.containsKey("payUserName")) {
                rule.setPayUserName(customizations.get("payUserName").toString());
            }
            if (customizations.containsKey("forUserName")) {
                rule.setForUserName(customizations.get("forUserName").toString());
            }
            if (customizations.containsKey("frequency")) {
                rule.setFrequency(customizations.get("frequency").toString());
            }
        }
        
        // 计算下次执行时间
        calculateNextExecuteTime(rule);
        
        // 保存规则
        autoAccountingRuleDao.insert(rule);
        
        return rule;
    }
    
    @Override
    public Map<String, Object> batchEnableRules(List<String> ruleIds) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failedCount = 0;
        List<String> failedIds = new ArrayList<>();
        
        for (String ruleId : ruleIds) {
            try {
                AutoAccountingRule rule = getRuleById(ruleId);
                if (rule != null && !rule.getIsActive()) {
                    rule.setIsActive(true);
                    calculateNextExecuteTime(rule);
                    if (autoAccountingRuleDao.update(rule) > 0) {
                        successCount++;
                    } else {
                        failedCount++;
                        failedIds.add(ruleId);
                    }
                } else {
                    failedCount++;
                    failedIds.add(ruleId);
                }
            } catch (Exception e) {
                failedCount++;
                failedIds.add(ruleId);
            }
        }
        
        result.put("successCount", successCount);
        result.put("failedCount", failedCount);
        result.put("failedIds", failedIds);
        result.put("totalCount", ruleIds.size());
        
        return result;
    }
    
    @Override
    public Map<String, Object> batchDisableRules(List<String> ruleIds) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failedCount = 0;
        List<String> failedIds = new ArrayList<>();
        
        for (String ruleId : ruleIds) {
            try {
                AutoAccountingRule rule = getRuleById(ruleId);
                if (rule != null && rule.getIsActive()) {
                    rule.setIsActive(false);
                    if (autoAccountingRuleDao.update(rule) > 0) {
                        successCount++;
                    } else {
                        failedCount++;
                        failedIds.add(ruleId);
                    }
                } else {
                    failedCount++;
                    failedIds.add(ruleId);
                }
            } catch (Exception e) {
                failedCount++;
                failedIds.add(ruleId);
            }
        }
        
        result.put("successCount", successCount);
        result.put("failedCount", failedCount);
        result.put("failedIds", failedIds);
        result.put("totalCount", ruleIds.size());
        
        return result;
    }
    
    @Override
    public Map<String, Object> batchDeleteRules(List<String> ruleIds) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failedCount = 0;
        List<String> failedIds = new ArrayList<>();
        
        for (String ruleId : ruleIds) {
            try {
                if (autoAccountingRuleDao.deleteById(ruleId) > 0) {
                    successCount++;
                } else {
                    failedCount++;
                    failedIds.add(ruleId);
                }
            } catch (Exception e) {
                failedCount++;
                failedIds.add(ruleId);
            }
        }
        
        result.put("successCount", successCount);
        result.put("failedCount", failedCount);
        result.put("failedIds", failedIds);
        result.put("totalCount", ruleIds.size());
        
        return result;
    }
    
    @Override
    public String exportRules(String format) {
        try {
            List<AutoAccountingRule> allRules = autoAccountingRuleDao.selectAllRules();
            
            if ("json".equalsIgnoreCase(format)) {
                // 转换为JSON格式
                return convertRulesToJson(allRules);
            } else {
                // 默认CSV格式
                return convertRulesToCsv(allRules);
            }
        } catch (Exception e) {
            return "导出失败: " + e.getMessage();
        }
    }
    
    @Override
    public Map<String, Object> importRules(String importData) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // TODO: 实现规则导入逻辑
            result.put("success", true);
            result.put("message", "导入成功");
            result.put("importedCount", 0);
            result.put("failedCount", 0);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "导入失败: " + e.getMessage());
            result.put("importedCount", 0);
            result.put("failedCount", 0);
        }
        
        return result;
    }
    
    @Override
    public List<String> checkRuleConflicts(AutoAccountingRule rule) {
        List<String> conflicts = new ArrayList<>();
        
        try {
            // 检查是否有重复的规则名称
            List<AutoAccountingRule> existingRules = autoAccountingRuleDao.selectByCondition(
                rule.getRuleName(), null, null, null);
            
            for (AutoAccountingRule existingRule : existingRules) {
                if (!existingRule.getId().equals(rule.getId())) {
                    conflicts.add("规则名称 '" + rule.getRuleName() + "' 已存在");
                    break;
                }
            }
            
            // 检查时间冲突
            if (rule.getStartDate() != null && rule.getEndDate() != null) {
                if (rule.getStartDate().isAfter(rule.getEndDate())) {
                    conflicts.add("开始日期不能晚于结束日期");
                }
            }
            
            // 检查频率值冲突
            if ("WEEKLY".equals(rule.getFrequency()) && (rule.getFrequencyValue() == null || rule.getFrequencyValue() < 1 || rule.getFrequencyValue() > 7)) {
                conflicts.add("周频率值必须在1-7之间");
            }
            
            if ("MONTHLY".equals(rule.getFrequency()) && (rule.getFrequencyValue() == null || rule.getFrequencyValue() < 1 || rule.getFrequencyValue() > 31)) {
                conflicts.add("月频率值必须在1-31之间");
            }
            
        } catch (Exception e) {
            conflicts.add("检查冲突时发生错误: " + e.getMessage());
        }
        
        return conflicts;
    }
    
    @Override
    public Map<String, Object> getRuleExecutionSuggestions(String ruleId) {
        Map<String, Object> suggestions = new HashMap<>();
        
        try {
            AutoAccountingRule rule = getRuleById(ruleId);
            if (rule == null) {
                suggestions.put("error", "规则不存在");
                return suggestions;
            }
            
            // 分析规则执行情况
            List<AutoAccountingExecutionLog> history = getExecutionHistory(ruleId);
            
            if (history.isEmpty()) {
                suggestions.put("suggestion", "这是新规则，建议先手动执行一次测试");
                suggestions.put("priority", "HIGH");
            } else {
                // 分析执行成功率
                long successCount = history.stream()
                    .filter(log -> "SUCCESS".equals(log.getExecuteResult()))
                    .count();
                double successRate = (double) successCount / history.size();
                
                if (successRate < 0.8) {
                    suggestions.put("suggestion", "执行成功率较低，建议检查规则配置");
                    suggestions.put("priority", "HIGH");
                } else if (successRate < 0.95) {
                    suggestions.put("suggestion", "执行成功率良好，可以继续使用");
                    suggestions.put("priority", "MEDIUM");
                } else {
                    suggestions.put("suggestion", "执行成功率很高，规则配置良好");
                    suggestions.put("priority", "LOW");
                }
                
                suggestions.put("successRate", String.format("%.1f%%", successRate * 100));
            }
            
        } catch (Exception e) {
            suggestions.put("error", "获取建议时发生错误: " + e.getMessage());
        }
        
        return suggestions;
    }
    
    @Override
    public boolean pauseRule(String ruleId) {
        try {
            AutoAccountingRule rule = getRuleById(ruleId);
            if (rule != null && rule.getIsActive()) {
                rule.setIsActive(false);
                return autoAccountingRuleDao.update(rule) > 0;
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public boolean resumeRule(String ruleId) {
        try {
            AutoAccountingRule rule = getRuleById(ruleId);
            if (rule != null && !rule.getIsActive()) {
                rule.setIsActive(true);
                calculateNextExecuteTime(rule);
                return autoAccountingRuleDao.update(rule) > 0;
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public List<Map<String, Object>> getRuleExecutionSchedule(String ruleId) {
        List<Map<String, Object>> schedule = new ArrayList<>();
        
        try {
            AutoAccountingRule rule = getRuleById(ruleId);
            if (rule == null || !rule.getIsActive()) {
                return schedule;
            }
            
            // 生成未来10次的执行计划
            LocalDateTime currentTime = LocalDateTime.now();
            LocalDateTime nextTime = rule.getNextExecuteTime() != null ? rule.getNextExecuteTime() : currentTime;
            
            for (int i = 0; i < 10; i++) {
                Map<String, Object> scheduleItem = new HashMap<>();
                scheduleItem.put("executionNumber", i + 1);
                scheduleItem.put("plannedTime", nextTime.toString());
                scheduleItem.put("status", i == 0 ? "即将执行" : "计划中");
                
                schedule.add(scheduleItem);
                
                // 计算下次执行时间
                AutoAccountingRule tempRule = new AutoAccountingRule();
                tempRule.setFrequency(rule.getFrequency());
                tempRule.setFrequencyValue(rule.getFrequencyValue());
                tempRule.setWeekdays(rule.getWeekdays());
                tempRule.setMonthDays(rule.getMonthDays());
                tempRule.setNextExecuteTime(nextTime);
                
                calculateNextExecuteTime(tempRule);
                nextTime = tempRule.getNextExecuteTime();
                
                if (nextTime == null) {
                    break;
                }
            }
            
        } catch (Exception e) {
            // 如果发生错误，返回空列表
        }
        
        return schedule;
    }
    
    // 私有辅助方法
    
    private boolean shouldExecuteRule(AutoAccountingRule rule) {
        LocalDateTime now = LocalDateTime.now();
        
        // 检查是否在有效期内
        if (rule.getStartDate() != null && now.toLocalDate().isBefore(rule.getStartDate())) {
            return false;
        }
        
        if (rule.getEndDate() != null && now.toLocalDate().isAfter(rule.getEndDate())) {
            return false;
        }
        
        // 检查是否到了执行时间
        if (rule.getNextExecuteTime() != null && now.isBefore(rule.getNextExecuteTime())) {
            return false;
        }
        
        // 检查工作日限制
        if (rule.getWeekdays() != null && !rule.getWeekdays().isEmpty()) {
            int currentWeekday = now.getDayOfWeek().getValue();
            if (!rule.getWeekdays().contains(String.valueOf(currentWeekday))) {
                return false;
            }
        }
        
        // 检查月份日期限制
        if (rule.getMonthDays() != null && !rule.getMonthDays().isEmpty()) {
            int currentDay = now.getDayOfMonth();
            if (!rule.getMonthDays().contains(String.valueOf(currentDay))) {
                return false;
            }
        }
        
        return true;
    }
    
    private CashBook createCashBookFromRule(AutoAccountingRule rule) {
        try {
            CashBook cashBook = new CashBook();
            cashBook.setId(UUID.randomUUID().toString());
            cashBook.setAmount(rule.getAmount());
            cashBook.setConsumerDate(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            cashBook.setPayUserName(rule.getPayUserName());
            cashBook.setForUserName(rule.getForUserName());
            cashBook.setPayWay(rule.getPayWay());
            cashBook.setPayPlat(rule.getPayPlat());
            cashBook.setRemark(rule.getRemark() + " [自动记账]");
            cashBook.setCreateBy(rule.getCreateBy());
            
            // 设置时间相关字段
            Date now = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
            cashBook.setQuarter(DateUtil.getQuarterOfYear(now));
            cashBook.setWeek(DateUtil.getWeekOfYear(now));
            cashBook.setMonth(DateUtil.getMonthOfYear(now));
            
            return cashBook;
        } catch (Exception e) {
            log.error("创建记账记录时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("创建记账记录失败: " + e.getMessage(), e);
        }
    }
    
    private void updateRuleExecutionInfo(AutoAccountingRule rule) {
        try {
            rule.setLastExecuteTime(LocalDateTime.now());
            rule.setExecuteCount(rule.getExecuteCount() + 1);
            calculateNextExecuteTime(rule);
            
            int updateResult = autoAccountingRuleDao.updateExecutionInfo(
                rule.getId(),
                rule.getLastExecuteTime(),
                rule.getNextExecuteTime(),
                rule.getExecuteCount()
            );
            
            if (updateResult <= 0) {
                log.warn("更新规则 {} 执行信息失败", rule.getId());
            }
        } catch (Exception e) {
            log.error("更新规则 {} 执行信息时发生错误: {}", rule.getId(), e.getMessage(), e);
            throw e; // 重新抛出异常，让事务回滚
        }
    }
    
    private AutoAccountingExecutionLog createExecutionLog(String ruleId, String result, String errorMessage, String cashBookId) {
        AutoAccountingExecutionLog log = new AutoAccountingExecutionLog();
        log.setId(UUID.randomUUID().toString());
        log.setRuleId(ruleId);
        log.setExecuteTime(LocalDateTime.now());
        log.setExecuteResult(result);
        log.setErrorMessage(errorMessage);
        log.setCashBookId(cashBookId);
        
        return log;
    }
    
    private LocalDateTime calculateNextDailyTime(AutoAccountingRule rule, LocalDateTime now) {
        LocalDateTime nextTime = now.with(LocalTime.of(0, 0, 0)).plusDays(1);
        
        // 如果有工作日限制，需要跳过非工作日
        if (rule.getWeekdays() != null && !rule.getWeekdays().isEmpty()) {
            while (!rule.getWeekdays().contains(String.valueOf(nextTime.getDayOfWeek().getValue()))) {
                nextTime = nextTime.plusDays(1);
            }
        }
        
        return nextTime;
    }
    
    private LocalDateTime calculateNextWeeklyTime(AutoAccountingRule rule, LocalDateTime now) {
        if (rule.getFrequencyValue() == null) {
            return now.plusWeeks(1);
        }
        
        LocalDateTime nextTime = now.with(LocalTime.of(0, 0, 0));
        
        // 计算到下一个指定星期的天数
        int currentWeekday = now.getDayOfWeek().getValue();
        int targetWeekday = rule.getFrequencyValue();
        
        int daysToAdd = targetWeekday - currentWeekday;
        if (daysToAdd <= 0) {
            daysToAdd += 7;
        }
        
        nextTime = nextTime.plusDays(daysToAdd);
        
        return nextTime;
    }
    
    private LocalDateTime calculateNextMonthlyTime(AutoAccountingRule rule, LocalDateTime now) {
        if (rule.getFrequencyValue() == null) {
            return now.plusMonths(1);
        }
        
        LocalDateTime nextTime = now.with(LocalTime.of(0, 0, 0));
        
        // 计算到下一个指定日期的天数
        int currentDay = now.getDayOfMonth();
        int targetDay = rule.getFrequencyValue();
        
        if (currentDay >= targetDay) {
            nextTime = nextTime.plusMonths(1);
        }
        
        // 设置目标日期
        nextTime = nextTime.withDayOfMonth(targetDay);
        
        return nextTime;
    }
    
    private LocalDateTime calculateNextYearlyTime(AutoAccountingRule rule, LocalDateTime now) {
        LocalDateTime nextTime = now.with(LocalTime.of(0, 0, 0)).plusYears(1);
        
        // 如果有月份日期限制，需要调整到指定日期
        if (rule.getMonthDays() != null && !rule.getMonthDays().isEmpty()) {
            String[] monthDayParts = rule.getMonthDays().split(",");
            if (monthDayParts.length >= 2) {
                int month = Integer.parseInt(monthDayParts[0]);
                int day = Integer.parseInt(monthDayParts[1]);
                nextTime = nextTime.withMonth(month).withDayOfMonth(day);
            }
        }
        
        return nextTime;
    }
    
    private AutoAccountingRuleTemplate createDefaultTemplate(String name, String category, String description) {
        AutoAccountingRuleTemplate template = new AutoAccountingRuleTemplate();
        template.setId(UUID.randomUUID().toString());
        template.setTemplateName(name);
        template.setCategory(category);
        template.setDescription(description);
        template.setIsActive(true);
        template.setUsageCount(0);
        template.setVersion("1.0");
        template.setAuthor("系统");
        
        // 根据分类设置默认值
        switch (category) {
            case "EXPENSE":
                template.setDefaultAmount(new BigDecimal("-100"));
                template.setDefaultPayUserName("我");
                template.setDefaultForUserName("商家");
                template.setDefaultPayWay("支付宝");
                template.setDefaultFrequency("DAILY");
                break;
            case "INCOME":
                template.setDefaultAmount(new BigDecimal("5000"));
                template.setDefaultPayUserName("公司");
                template.setDefaultForUserName("我");
                template.setDefaultPayWay("银行转账");
                template.setDefaultFrequency("MONTHLY");
                template.setDefaultFrequencyValue(1);
                break;
            default:
                template.setDefaultAmount(new BigDecimal("0"));
                template.setDefaultFrequency("DAILY");
        }
        
        return template;
    }
    
    private String convertRulesToJson(List<AutoAccountingRule> rules) {
        // TODO: 实现JSON转换
        return "{\"rules\": " + rules.size() + "}";
    }
    
    private String convertRulesToCsv(List<AutoAccountingRule> rules) {
        // TODO: 实现CSV转换
        StringBuilder csv = new StringBuilder();
        csv.append("规则名称,规则类型,金额,频率,状态\n");
        
        for (AutoAccountingRule rule : rules) {
            csv.append(rule.getRuleName()).append(",")
               .append(rule.getRuleType()).append(",")
               .append(rule.getAmount()).append(",")
               .append(rule.getFrequency()).append(",")
               .append(rule.getIsActive() ? "启用" : "禁用").append("\n");
        }
        
        return csv.toString();
    }
    
    // 私有辅助方法：排序规则
    private List<AutoAccountingRule> sortRules(List<AutoAccountingRule> rules, String sortBy, String sortOrder) {
        if (sortBy == null || sortBy.isEmpty()) {
            return rules;
        }
        
        Comparator<AutoAccountingRule> comparator = null;
        
        switch (sortBy.toLowerCase()) {
            case "name":
                comparator = Comparator.comparing(rule -> rule.getRuleName() != null ? rule.getRuleName() : "");
                break;
            case "amount":
                comparator = Comparator.comparing(rule -> rule.getAmount() != null ? rule.getAmount() : BigDecimal.ZERO);
                break;
            case "createdat":
                comparator = Comparator.comparing(rule -> rule.getCreateDate() != null ? rule.getCreateDate() : new Date());
                break;
            case "updatedat":
                comparator = Comparator.comparing(rule -> rule.getCreateDate() != null ? rule.getCreateDate() : new Date());
                break;
            case "status":
                comparator = Comparator.comparing(rule -> rule.getIsActive() != null ? rule.getIsActive() : false);
                break;
            default:
                comparator = Comparator.comparing(rule -> rule.getCreateDate() != null ? rule.getCreateDate() : new Date());
        }
        
        if ("DESC".equalsIgnoreCase(sortOrder)) {
            comparator = comparator.reversed();
        }
        
        return rules.stream().sorted(comparator).collect(Collectors.toList());
    }
}
